package com.gaoxk.asserviceinterceptor;


import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.Phase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 入站日志拦截器（与修复后的出站拦截器配套）
 */
public class PureLoggingOutInterceptor extends AbstractSoapInterceptor {
    private static final Logger log = LoggerFactory.getLogger(PureLoggingOutInterceptor.class);
    // 存储请求ID与开始时间的映射（线程安全）
    private final ConcurrentHashMap<Long, Long> requestStartTimeMap = new ConcurrentHashMap<>();

    public PureLoggingOutInterceptor() {
        super(Phase.READ); // 在读取请求阶段拦截
    }

    @Override
    public void handleMessage(SoapMessage message) throws Fault {
        // 生成唯一请求ID
        final Long requestId = System.currentTimeMillis() + (long) (Math.random() * 1000);
        message.put("REQUEST_ID", requestId); // 存入消息中供出站拦截器使用

        // 记录请求开始时间
        long startTime = System.currentTimeMillis();
        requestStartTimeMap.put(requestId, startTime);

        try {
            // 打印请求基本信息
            log.info("===== 请求[{}] 开始 [{}] =====", requestId, startTime);

            // 打印HTTP请求头
            printHttpRequestHeaders(message, requestId);

            // 打印SOAP请求头
            printSoapRequestHeaders(message, requestId);

            // 读取并打印SOAP请求报文
            InputStream is = message.getContent(InputStream.class);
            if (is != null) {
                // 缓存请求流内容
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = is.read(buffer)) != -1) {
                    baos.write(buffer, 0, len);
                }
                baos.flush();

                // 重置输入流供后续处理
                byte[] requestBytes = baos.toByteArray();
                message.setContent(InputStream.class, new java.io.ByteArrayInputStream(requestBytes));

                // 格式化并打印请求报文
                String requestXml = new String(requestBytes, StandardCharsets.UTF_8);
                String formattedXml = PureLoggingInInterceptor.formatXml(requestXml);
                log.debug("请求[{}] SOAP报文：\n{}", requestId, formattedXml);
            }

        } catch (Exception e) {
            log.error("请求[{}]日志处理失败", requestId, e);
            requestStartTimeMap.remove(requestId); // 清理失败的请求记录
        }
    }

    /**
     * 获取请求开始时间（供出站拦截器使用）
     */
    public long getStartTime(Long requestId) {
        Long startTime = requestStartTimeMap.get(requestId);
        return startTime != null ? startTime : System.currentTimeMillis();
    }

    /**
     * 清理请求记录（防止内存泄漏）
     */
    public void removeStartTime(Long requestId) {
        requestStartTimeMap.remove(requestId);
    }

    /**
     * 打印HTTP请求头
     */
    private void printHttpRequestHeaders(SoapMessage message, Long requestId) {
        try {
            Map<String, Object> headers = (Map<String, Object>) message.get(Message.PROTOCOL_HEADERS);
            if (headers != null && !headers.isEmpty()) {
                log.info("请求[{}] HTTP头信息：", requestId);
                for (Map.Entry<String, Object> entry : headers.entrySet()) {
                    log.info("请求[{}]   {}: {}", requestId, entry.getKey(), entry.getValue());
                }
            }
        } catch (Exception e) {
            log.warn("请求[{}]读取HTTP头失败", requestId, e);
        }
    }

    /**
     * 打印SOAP请求头
     */
    private void printSoapRequestHeaders(SoapMessage message, Long requestId) {
        try {
            List<Header> soapHeaders = message.getHeaders();
            if (soapHeaders != null && !soapHeaders.isEmpty()) {
                log.info("请求[{}] SOAP头信息：", requestId);
                for (Header header : soapHeaders) {
                    log.info("请求[{}]   {}: {}", requestId, header.getName(), header.getObject());
                }
            }
        } catch (Exception e) {
            log.warn("请求[{}]读取SOAP头失败", requestId, e);
        }
    }

    /**
     * 简易XML格式化（静态方法，供出站拦截器使用）
     */
//    public static String formatXml(String xml) {
//        if (xml == null || xml.trim().isEmpty()) {
//            return "空报文";
//        }
//        // 简易格式化：替换标签换行
//        return xml.replace("><", ">\n<")
//                .replace("<", "  <")
//                .replace("</", "\n</")
//                .replace(">", ">\n");
//    }
}

